# coding: utf-8

import sys
import pprint
from ve_surprisal_dual import VotingExperts, compress_bz2, compress_zlib

def get_data():
    #with open('data/uav-train.txt') as data:
    with open('data/bl-uav-sim.txt') as data:
        lessons = [d.split('*') for d in data.read().split('**')]
        
    sequence = []
    boundaries = []
    for l in lessons:
        boundaries += [0] * (len(l)-1)
        boundaries.append(1)
        for le in l:
            sequence.append(le)
    boundaries.pop()
    
    return sequence, boundaries
    
# returns the number of true positives, true negatives, false positives and 
# false negatives
def compare(true_boundaries, predicted_boundaries):
    tp = tn = fp = fn = 0.0
    for tb, pb in zip(true_boundaries, predicted_boundaries):
        if tb == pb:
            if pb == 1:
                tp += 1
            else:
                tn += 1
        else:
            if pb == 1:
                fp += 1
            else:
                fn += 1
    return tp, tn, fp, fn
    
# returns the accuracy, precision, recall and fscore
def performance(tp, tn, fp, fn):
    accuracy = (tp + tn) / (tp + tn + fp + fn)
    precision = tp / (tp + fp)
    recall = tp / (tp + fn)
    fscore = 2 * (precision * recall) / (precision + recall)
    return accuracy, precision, recall, fscore

if __name__ == '__main__':
    sequence, boundaries = get_data()

    # calculate the performance of voting experts with
    # different window sizes, thresholds, and compression methods
    i = 0
    results = []
    for ws in range(3, 10):
        for th in range(1, 2*2*ws+1):
            for compress in (compress_bz2, compress_zlib):
                ve = VotingExperts(sequence, ws, compress)
                predicted_boundaries = ve.threshold(th)
                
                tp, tn, fp, fn = compare(boundaries, predicted_boundaries)
                if tp == 0: continue
                accuracy, precision, recall, fscore = performance(tp,tn,fp,fn)
                
                results.append({
                    'tp': tp,
                    'tn': tn,
                    'fp': fp,
                    'fn': fn,
                    'winsize': ws,
                    'threshold': th,
                    'accuracy': accuracy,
                    'precision': precision,
                    'recall': recall,
                    'fscore': fscore,
                    'compress': compress.__name__.split('_')[1],
                })
    
                i+=1
                sys.stdout.write('.')
                sys.stdout.flush()
    
    print
    # print the best 5 parameters based on the fscore
    print boundaries
    print
    for res in sorted(results, key=lambda k: k['fscore'])[-5:]:
        pprint.pprint(res)
        print
        
    # print the performance of NCD
    print '--------'
    ncd_boundaries = [(1 if x > .4 else 0) for x in ve.ncd()]
    tp, tn, fp, fn = compare(boundaries, ncd_boundaries)
    accuracy, precision, recall, fscore = performance(tp, tn, fp, fn)
    
    print 'ncd:'
    pprint.pprint({
        'tp': tp,
        'tn': tn,
        'fp': fp,
        'fn': fn,
        'accuracy': accuracy,
        'precision': precision,
        'recall': recall,
        'fscore': fscore,
    })

    # textual histogram
    bucket_size = 0.05
    buckets = []
    for n in range(int(1/bucket_size)):
        buckets.append(0)
    for res in results:
        buckets[int(res['fscore']/bucket_size)] += 1
    print
    for i, count in enumerate(buckets):
        print i*bucket_size, count
    
    # print '--------'
    # ve = VotingExperts(sequence, results[-1]['winsize'], compress_zlib)
    # predicted_boundaries = ve.threshold(results[-1]['threshold'])
    # 
    # for b,p,x in zip(boundaries, predicted_boundaries, ncd_boundaries):
    #     print b, '---', p, '---', x
